/*
 * Copyright (c) Huawei Device Co., Ltd. 2024. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "ref_ar_do.h"
#include "common_utils.h"

namespace OHOS {
namespace SE {
using namespace std;

/*
 * Software that is part of the Secure Element access API, it obtains access
 * rules from the Secure Element and applies those rules to restrict device
 * application access to the various Secure Element applications.
 */
RefArDo::RefArDo(std::vector<uint8_t> rawData)
    : BerTlv(rawData, REF_AR_DO_TAG)
{
    rawData_ = rawData;
    doTag_ = REF_AR_DO_TAG;
}

RefArDo::RefArDo(std::vector<uint8_t> payload, bool isPayload)
    : BerTlv(payload, isPayload, REF_AR_DO_TAG)
{
    doTag_ = REF_AR_DO_TAG;
}

RefArDo::~RefArDo()
{
}

bool RefArDo::GetRefDoAndArDo(vector<RefDo> &retRefDo, vector<ArDo> &retArDo)
{
    uint32_t tag;
    if (!GetDoTag(tag) || tag != REF_AR_DO_TAG) {
        return false;
    }
    vector<uint8_t> payload;
    if (!GetDoPayload(payload)) {
        return false;
    }
    // parse refardo from payload
    if (payload.empty() || payload.size() == 0) {
        ErrorLog("No REF_AR_DO.");
        return false;
    }
    uint32_t startIndex = 0;
    uint32_t length = 0;
    std::vector<uint8_t> refDoData;
    std::vector<uint8_t> arDoData;
    do {
        // get refDo
        if (payload[startIndex] != REF_DO_TAG) {
            ErrorLog("invalid RefDo header.");
            return false;
        }
        std::vector<uint8_t> tmpForRefDo;
        tmpForRefDo.assign(payload.begin() + 1, payload.end());
        uint32_t tmpPayloadStartIndex;
        ParseLength(tmpForRefDo, length, tmpPayloadStartIndex);
        std::string payloadStr = CommonUtils::BytesArrayToHexString(&payload[0], payload.size());
        InfoLog("payloadStr = %{public}s, startIndex %{public}d, length %{public}d, payload.size() %{public}lu,.",
            payloadStr.c_str(), startIndex, length, payload.size());
        if (payload.size() < startIndex + 1 + length) {
            ErrorLog("invalid RefDo length.");
            return false;
        }
        std::vector<uint8_t> tmpRefDoData;
        tmpRefDoData.assign(payload.begin() + startIndex,
            payload.begin() + startIndex +1 + tmpPayloadStartIndex + length);
        std::string refstr = CommonUtils::BytesArrayToHexString(&tmpRefDoData[0], tmpRefDoData.size());
        InfoLog("RefDo : %{public}s.", refstr.c_str());
        RefDo tmpRefDo = RefDo(tmpRefDoData);
        retRefDo.push_back(tmpRefDo);
        startIndex = tmpPayloadStartIndex + length + 1;
        // get arDo
        if (payload[startIndex] != AR_DO_TAG) {
            ErrorLog("invalid ArDo header.");
            return false;
        }
        std::vector<uint8_t> tmpForArDo;
        tmpForArDo.assign(payload.begin() + startIndex + 1, payload.end());
        uint32_t tmpArPayloadStartIndex;
        ParseLength(tmpForArDo, length, tmpArPayloadStartIndex);
        if (payload.size() < startIndex + 1 + length) {
            ErrorLog("invalid ArDo length.");
            return false;
        }
        vector<uint8_t> tmpArDoData;
        tmpArDoData.assign(payload.begin() + startIndex,
            payload.begin() + startIndex + length + 1 + tmpArPayloadStartIndex);
        std::string arstr = CommonUtils::BytesArrayToHexString(&tmpArDoData[0], tmpArDoData.size());
        InfoLog("ArDo : %{public}s.", arstr.c_str());
        ArDo tmpArDo = ArDo(tmpArDoData);
        retArDo.push_back(tmpArDo);
    } while (0);
    return true;
}

bool RefArDo::MergeRefArDo(vector<RefDo> &retRefDo, vector<ArDo> &retArDo)
{
    return true;
}
}  // namespace SE
}  // namespace OHOS
